package com.aleyn.router.util

import com.aleyn.router.LRouter
import com.aleyn.router.core.NavCallback
import com.aleyn.router.core.Navigator

/**
 * @author: Aleyn
 * @date: 2023/7/17 16:05
 */

/**
 * [LRouter] 的扩展函数，提供一个便捷的 DSL 风格导航方法。
 *
 * @param url 目标路径。
 * @param block 一个作用域为 [Navigator.Builder] 的 lambda，用于配置导航选项 (如添加参数、动画等)。
 */
fun LRouter.navigator(url: String, block: Navigator.Builder.() -> Unit = {}) {
    build(url).apply(block).navigation()
}

/**
 * [LRouter] 的扩展函数，用于便捷地获取 Fragment 实例。
 *
 * @param url 目标 Fragment 的路径。
 * @return 匹配路径的 Fragment 实例，如果找不到则返回 null。
 */
fun LRouter.getFragment(url: String) = build(url).getFragment()

/**
 * [Navigator.Builder] 的扩展函数，用于设置完整的导航回调。
 *
 * @param onInterrupt 导航被中断时的回调。
 * @param onLost 未找到目标页面时的回调。
 * @param onFound 找到目标页面时的回调。
 * @param onArrival 成功到达目标页面时的回调。
 */
fun Navigator.Builder.navCallback(
    onInterrupt: (navigator: Navigator) -> Unit = {},
    onLost: (navigator: Navigator) -> Unit = {},
    onFound: (navigator: Navigator) -> Unit = {},
    onArrival: (navigator: Navigator) -> Unit = {},
) {
    navigation(null, navBack(onInterrupt, onLost, onFound, onArrival))
}

/**
 * [Navigator.Builder] 的扩展函数，仅设置导航被中断时的回调。
 */
fun Navigator.Builder.navInterrupt(onInterrupt: (navigator: Navigator) -> Unit) {
    navigation(null, navBack(onInterrupt))
}

/**
 * [Navigator.Builder] 的扩展函数，仅设置未找到目标页面时的回调。
 */
fun Navigator.Builder.navLost(onLost: (navigator: Navigator) -> Unit) {
    navigation(null, navBack(onLost = onLost))
}

/**
 * [Navigator.Builder] 的扩展函数，仅设置找到目标页面时的回调。
 */
fun Navigator.Builder.navFound(onFound: (navigator: Navigator) -> Unit) {
    navigation(null, navBack(onFound = onFound))
}

/**
 * [Navigator.Builder] 的扩展函数，仅设置成功到达目标页面时的回调。
 */
fun Navigator.Builder.navArrival(onArrival: (navigator: Navigator) -> Unit) {
    navigation(null, navBack(onArrival = onArrival))
}

/**
 * 创建一个 [NavCallback] 实例的私有辅助函数。
 */
private fun navBack(
    onInterrupt: (navigator: Navigator) -> Unit = {},
    onLost: (navigator: Navigator) -> Unit = {},
    onFound: (navigator: Navigator) -> Unit = {},
    onArrival: (navigator: Navigator) -> Unit = {},
): NavCallback = object : NavCallback {
    override fun onLost(navigator: Navigator) {
        onLost(navigator)
    }

    override fun onFound(navigator: Navigator) {
        onFound(navigator)
    }

    override fun onArrival(navigator: Navigator) {
        onArrival(navigator)
    }

    override fun onInterrupt(navigator: Navigator) {
        onInterrupt(navigator)
    }
}